package com.framework.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.framework.dao.MerchantDao;
import com.framework.entity.sys.SysAgent;
import com.framework.entity.sys.SysDict;
import com.framework.entity.ter.TerDistribu;
import com.framework.entity.ter.TerMerchantReport;
import com.framework.entity.ter.TerTerminalInfo;
import com.framework.entity.tran.TranTransactionInfo;
import com.framework.exception.RRException;
import com.framework.exception.menu.RespCode;
import com.framework.page.PageUtils;
import com.framework.redis.util.RedisUtil;
import com.framework.service.*;
import com.framework.service.yhbservice.YhbRecommendMerchantService;
import com.framework.utils.DateUtils;
import com.framework.utils.string.StringUtil;
import com.framework.validator.Assert;
import com.framework.view.TerminalOwnDto;
import com.framework.yhbEntity.user.YhbRecommendMerchant;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("merchantService")
public class MerchantServiceImpl extends ServiceImpl<MerchantDao, TerMerchantReport> implements MerchantService {

    @Autowired
    private AgentService agentService;
    @Autowired
    private DistribuService distribuService;

    @Autowired
    private TerminalInfoService terminalInfoService;
    @Autowired
    private TransactionInfoService transactionInfoService;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private DictService dictService;

    @Autowired
    private ActiveService activeService;
    @Autowired
    private YhbRecommendMerchantService yhbRecommendMerchantService;

    @Autowired
    private TerFlowInfoService terFlowInfoService;

    @Override
    public int queryMerchantCount(Long agentId, Integer type, Integer isOwn) {
        if (type == null || type == 0) {
            throw new RRException("9000", "type不能为空");
        }
        int count = baseMapper.queryMerchantCount(agentId, type, isOwn);
        return count;
    }

    @Override
    public TerMerchantReport queryMerchantBySn(String sn) {
        Assert.isBlank(sn, "终端号不能为空");
        TerMerchantReport r = new TerMerchantReport();
        r.setSn(sn);
        return baseMapper.selectOne(r);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void repMerchant(String merchantName, String phone, String sn, String model, String token, String merchantNo) {
        if (StringUtils.isBlank(merchantName) ||
                StringUtils.isBlank(phone) ||
                StringUtils.isBlank(sn) ||
                StringUtils.isBlank(token)) {
            throw new RRException(RespCode.NOT_PARAM_ERROR);
        }
        //缓存中代理商信息
        SysAgent agent = agentService.queryAgentByToken(token);

        reportMerchant(merchantName, phone, sn, merchantNo, agent);


    }

    private void reportMerchant(String merchantName, String phone, String sn, String merchantNo, SysAgent agent) {
        Long agentAgentId = agent.getAgentId();

        Long deptId = agent.getDeptId();
        //查询平台id
        SysAgent baseAgent = agentService.queryBasicAgentBydeptId(deptId);
        if (baseAgent.getAgentId().equals(agentAgentId)) {
            throw new RRException("9000", "请勿使用平台报备");
        }

        //当前报备商户的顶级盟主
        SysAgent topAgent = agentService.queryTopAgentBySubIdAndBase(agentAgentId, baseAgent.getAgentId());
        if (topAgent == null) {
            throw new RRException("9000", "未查询到您的顶级盟主,请核对登录账号");
        }
        TerMerchantReport merchant = queryMerchantBySn(sn);
        if (merchant != null) {
            throw new RRException("9000", "此机器已经完成商户报备");
        }

        TerTerminalInfo t = terminalInfoService.queryTerminalBySn(sn);
        if (t == null) {
            throw new RRException("9000", "错误的终端号");
        }
        if (t.getIsReport() == 2) {
            throw new RRException("9000", "此机器已经完成商户报备");
        }

        Long agentId = distribuService.queryTerminalOwn(sn);
        if (agentId == null) {
            throw new RRException("9000", "未查询到终端所属人");
        }
        if (baseAgent.getAgentId().equals(agentId)) {
            throw new RRException("9000", "请勿报备平台所有机器");
        }
        //机器所属人的顶级盟主
        SysAgent terOwn = agentService.queryTopAgentBySubIdAndBase(agentId,baseAgent.getAgentId());
        if(terOwn==null){
            throw new RRException("9000","未查询到该机器所属人的顶级盟主");
        }

        //如果是顶级不相等,
        if(!terOwn.getAgentId().equals(topAgent.getAgentId())){
            throw new RRException("9000","该机器不属于您的团队");
        }

        //非顶级盟主报备，核实团队
        if (!topAgent.getAgentId().equals(agentAgentId)) {
            //查出机具归属人的顶级盟主
            if (!topAgent.getAgentId().equals(terOwn.getAgentId())) {
                throw new RRException("9000", "该机器不属于您的团队");
            }
        }

        merchantName=Assert.hasSpace(merchantName);
        phone=Assert.hasSpace(phone);


        //开始报备
        TerMerchantReport m = new TerMerchantReport();
        m.setSn(sn);
        m.setCreateDate(new Date());
        m.setMerchantName(merchantName);
        m.setPhone(phone);
        m.setAgentId(agentAgentId);
        m.setTerminalType(t.getTerminalType());
        m.setDeptId(t.getDeptId());
        insertMerchant(m);
        //是否是大pos机器，需要修改商户号码
        t.setIsReport(2L);

        //卡一的盛刷需要报备
        if (t.getDeptId().equals(889323L)) {
            if (t.getTerminalType() == 5) {
                String msg = "";
                if (t.getTerminalType() == 5) {
                    msg = "请填写盛刷机器的商户号";
                }

                if (StringUtils.isBlank(merchantNo)) {
                    throw new RRException("9000", msg);
                }
                t.setMerchantCode(merchantNo);
            }
            if (t.getTerminalType() == 7) {
                String msg = "";
                if (t.getTerminalType() == 7) {
                    msg = "请填写盛刷大pos机器的商户号";
                }

                if (StringUtils.isBlank(merchantNo)) {
                    throw new RRException("9000", msg);
                }
                t.setMerchantCode(merchantNo);
            }
        }
        //信创的开店宝需要报备
        if (t.getDeptId().equals(889324L)) {
            if (t.getTerminalType() == 1) {
                String msg = "";
                if (t.getTerminalType() == 1) {
                    msg = "请填写开店宝大pos的商户号";
                }

                if (StringUtils.isBlank(merchantNo)) {
                    throw new RRException("9000", msg);
                }
                t.setMerchantCode(merchantNo);
            }

        }
        terminalInfoService.updateTerminal(t);

        //核实机器是否属于报备人
        TerDistribu snDis = distribuService.queryDistribu(sn,agentAgentId);

        //如果不属于，则分配
        if (snDis == null) {
            distribuService.insertDistribu(sn, agentId, agentAgentId);
        }
        //添加流水
        terFlowInfoService.addReportInfo(sn,agent);

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        terFlowInfoService.addReportedInfo(sn,agent.getDeptId(),t);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertMerchant(TerMerchantReport t) {
        baseMapper.insert(t);
    }

    @Override
    public TerminalOwnDto queryMerchantOwnInfo(String sn) {
        Assert.isBlank(sn, "终端号不能为空");
        return baseMapper.queryMerchantOwnInfo(sn);
    }

    @Override
    public Map<String, Object> queryMerchantMap(String token, String types, Integer terminalType, String toDayAmount, String thisMonthAmount, String state, String isActivation, String keywords) {
        Map<String, Object> map = new HashedMap();
        //缓存中代理商信息
        SysAgent agent = agentService.queryAgentByToken(token);
        Long agentId = agent.getAgentId();
        Map<String, Object> params = new HashMap<>();

        params.put("agentId", agentId);
        params.put("types", types);
        params.put("terminalType", terminalType);
        params.put("toDayAmount", toDayAmount);
        params.put("thisMonthAmount", thisMonthAmount);
        params.put("state", state);
        params.put("isActivation", isActivation);
        params.put("keywords", keywords);
        List<Map<String, Object>> list = baseMapper.queryNewMerchantList(params);
        //昨天总交易量
        BigDecimal toDayAmountSum=list.stream()
                .map(e->new BigDecimal(e.get("toDayAmount").toString()))
                .reduce(BigDecimal.ZERO,BigDecimal::add);

        map.put("list", list);
        map.put("toDayAmountSum", toDayAmountSum);
        return map;
    }


    @Override
    public PageUtils queryMerchantPage(Map<String, Object> params) {

        if ("".equals(params.get("reportDate"))) {
            params.put("reportDate", null);
        }
        Integer pageSize = Integer.valueOf(params.get("limit").toString());
        Integer currPage = Integer.valueOf(params.get("page").toString());
        params.put("limit", pageSize);
        params.put("start", (currPage - 1) * pageSize);
        List<Map<String, Object>> list = baseMapper.queryMerchantInfoList(params);
        Integer totalCount = baseMapper.queryMerchantInfoCount(params);
        return new PageUtils(list, totalCount, pageSize, currPage);
    }

    @Override
    public Map<String, Object> queryMerchantByReportId(String token, String reportId) {
        Assert.isBlank(token, "token不能为空");
        Assert.isBlank(reportId, "商户id不能为空");
        SysAgent agent = agentService.queryAgentByToken(token);
        Long deptId = agent.getDeptId();
        Map<String, Object> info = baseMapper.queryMerchantByReportId(reportId, deptId);
        Long agentId = Long.valueOf(info.get("agentId").toString());

        if (!agent.getAgentId().equals(agentId)) {
            throw new RRException("9000", "该商户不属于你");
        }
        String sn = info.get("sn").toString();

        List<Map<String, Object>> list = transactionInfoService.queryListBySn(sn, null, null);

        BigDecimal totalAmount = list.stream().map(e -> new BigDecimal(e.get("amount").toString())).reduce(BigDecimal.ZERO, BigDecimal::add);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("info", info);
        resultMap.put("list", list);
        resultMap.put("totalAmount", totalAmount);
        return resultMap;
    }

    @Override
    public void deleteMerchant(String reportId) {
        TerMerchantReport m = baseMapper.selectById(reportId);
        TerTerminalInfo t = terminalInfoService.queryTerminalBySn(m.getSn());
        List<TranTransactionInfo> list = transactionInfoService.queryListBySnAndTime(m.getSn(), new Date());

        if (t.getIsActivation().intValue() == 2) {
            throw new RRException("9000", "该机器已激活");
        }
        if (list.size() > 0) {
            throw new RRException("9000", "该机器已有交易");
        }
        baseMapper.deleteMerById(reportId);
        t.setIsReport(1L);
        terminalInfoService.updateById(t);
    }

    @Override
    public Map<String, Object> getMerchantById(String reportId) {
        return baseMapper.getMerchantById(reportId);
    }

    @Override
    public void updateMerchant(Map<String, Object> merchant) {

        String sn=merchant.get("sn").toString();
        Assert.isBlank(sn,"sn不能为空");
        TerTerminalInfo t = terminalInfoService.queryTerminalBySn(sn);
        Assert.isNull(t,"未查询到sn对应得终端");

        String reportId = merchant.get("reportId").toString();
        TerMerchantReport m = baseMapper.selectById(reportId);
        m.setPhone(merchant.get("phone").toString());
        m.setMerchantName(merchant.get("merchantName").toString());
        m.setSn(sn);
        baseMapper.updateById(m);

    }

    @Override
    public List<TerMerchantReport> queryAllMerchantList(Long deptId) {
        return baseMapper.queryAllMerchantList(deptId);
    }

    @Override
    public String getMerchantCode(String token) {
        SysAgent agent = agentService.queryAgentByToken(token);
        String code = StringUtil.getRandomNumberString(6);
        String str = StringUtil.getDateString2(0);
        redisUtil.set(str + "-" + agent.getPhone() + "-" + code, code, 20 * 60);
        return code;
    }

    @Override
    public Map<String, Object> getYhbMerchant(String token, Integer state) {
        SysAgent agent = agentService.queryAgentByToken(token);
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> list = yhbRecommendMerchantService.getYhbMerchant(agent.getAgentId(), state);
        Integer noVerCount = yhbRecommendMerchantService.getYhbMerchantCount(agent.getAgentId(), 2);
        Integer hadVerCount = yhbRecommendMerchantService.getYhbMerchantCount(agent.getAgentId(), 1);
        result.put("list", list);
        result.put("noVerCount", noVerCount);
        result.put("hadVerCount", hadVerCount);
        return result;
    }

    @Override
    public void verifyMerchant(String token, Long id, String sn, Integer state) {
        if (state.intValue() == 2) {
            throw new RRException("9000", "审核状态不正确");
        }

        SysAgent agent = agentService.queryAgentByToken(token);
        if(id==null || id.intValue()==0){
            throw new RRException("9000","id不正确");
        }
        YhbRecommendMerchant rm = yhbRecommendMerchantService.selectById(id);
        if (rm == null) {
            throw new RRException("9000", "未查询到该推荐商户信息");
        }

        if (!agent.getAgentId().equals(rm.getAgentId())) {
            throw new RRException("9000", "该推荐商户不属于你");
        }

        Long agentAgentId = agent.getAgentId();

        Long deptId = agent.getDeptId();
        //查询平台id
        SysAgent baseAgent = agentService.queryBasicAgentBydeptId(deptId);
        if (baseAgent.getAgentId().equals(agentAgentId)) {
            throw new RRException("9000", "请勿使用平台账户");
        }

        //当前报备商户的顶级盟主
        SysAgent topAgent = agentService.queryTopAgentBySubIdAndBase(agentAgentId, baseAgent.getAgentId());
        if (topAgent == null) {
            throw new RRException("9000", "未查询到您的顶级盟主,请核对登录账号");
        }
        if (state.intValue() == 1) {

            YhbRecommendMerchant merchant = yhbRecommendMerchantService.queryRecommendBySn(sn);
            if (merchant != null) {
                throw new RRException("9000", "此机器已经被分配");
            }
            Long agentId = distribuService.queryTerminalOwn(sn);
            if (agentId == null) {
                throw new RRException("9000", "未查询到终端所属人");
            }
            if (baseAgent.getAgentId().equals(agentId)) {
                throw new RRException("9000", "请勿报备平台所有机器");
            }

            //非顶级盟主报备，核实团队
            if (!topAgent.getAgentId().equals(agentAgentId)) {
                //查出机具归属人的顶级盟主
                SysAgent topAgentBydistribu = agentService.queryTopAgentBySubIdAndBase(agentId, baseAgent.getAgentId());
                if (!topAgent.getAgentId().equals(topAgentBydistribu.getAgentId())) {
                    throw new RRException("9000", "该机器不属于您的团队");
                }
            }


            rm.setState(state);
            rm.setSn(sn);


            TerTerminalInfo t = terminalInfoService.queryTerminalBySn(sn);
            BigDecimal amount = t.getReapAmount();
            if (amount == null || amount.compareTo(new BigDecimal("50")) == -1) {
                throw new RRException("9000", "该机器返现金额不足");
            }

            if (t.getIsOnLine().intValue() == 0) {
                throw new RRException("9000", "该机器不参与返现");
            }
            if (t.getIsActivation().intValue() == 2) {
                throw new RRException("9000", "该机器已返现");
            }

            amount = amount.subtract(new BigDecimal("50"));
            t.setReapAmount(amount);
            terminalInfoService.updateById(t);
        } else if (state.intValue() == 3) {
            rm.setState(state);

        }
        yhbRecommendMerchantService.updateById(rm);


    }

    @Override
    public void reportMerByWX(String merchantName, String phone, String sn, String model, String merchantNo, String agentPhone, Long agentId) {
        SysAgent agent = agentService.queryAgentById(agentId);

        Assert.isNull(agent,"推荐码错误");

        if(!agent.getPhone().equals(agentPhone)){
            throw new RRException("9000","手机号与推荐码不匹配");
        }

        reportMerchant(merchantName, phone, sn, merchantNo, agent);

    }

    @Override
    public void repMerchant(String merchantName, String phone, String sn, String token, String merchantNo) {
        if (StringUtils.isBlank(merchantName) ||
                StringUtils.isBlank(phone) ||
                StringUtils.isBlank(sn) ||
                StringUtils.isBlank(token)) {
            throw new RRException(RespCode.NOT_PARAM_ERROR);
        }
        //缓存中代理商信息
        SysAgent agent = agentService.queryAgentByToken(token);

        phone=Assert.hasSpace(phone);

        if(phone.length()!=11){
            throw new RRException("9000","手机号码长度不对");
        }
        reportMerchant(merchantName, phone, sn, merchantNo, agent);
    }

    @Override
    public Map<String, Object> queryMerchantById(String token, String reportId) {
        Assert.isBlank(token, "token不能为空");
        Assert.isBlank(reportId, "商户id不能为空");
        SysAgent agent = agentService.queryAgentByToken(token);
        Long deptId = agent.getDeptId();
        Map<String, Object> info = baseMapper.queryMerchantById(reportId, deptId);
        Long agentId = Long.valueOf(info.get("agentId").toString());

        if (!agent.getAgentId().equals(agentId)) {
            throw new RRException("9000", "该商户不属于你");
        }
        String sn = info.get("sn").toString();

        String terminalType= info.get("terminalType").toString();

        SysDict terTypeLogo = dictService.querySysDict(deptId.intValue(),terminalType, "ter_type_logo");

        info.put("typeLogo",terTypeLogo!=null?terTypeLogo.getValue():"https://mpos-img.oss-cn-beijing.aliyuncs.com/logo/merinfologo/kayou@2x.png");

        List<Map<String, Object>> list = transactionInfoService.queryListBySn(sn, null, null);

        BigDecimal totalAmount = list.stream().map(e->new BigDecimal(e.get("amount").toString())).reduce(BigDecimal.ZERO,BigDecimal::add);

        Map<String, Object> resultMap = new HashMap<>(3);
        resultMap.put("info", info);
        resultMap.put("list", list);
        resultMap.put("totalAmount", totalAmount);
        return resultMap;
    }

    @Override
    public List<TerMerchantReport> checkMerchantAndDis() {
        return baseMapper.checkMerchantAndDis();
    }


    @Override
    public void handleNoTranMer(TerMerchantReport terMerchantReport) {
        //考拉伙伴 不进行回退
        if (terMerchantReport.getDeptId().equals(889326L)) {
            return;
        }
        //卡一不回退
        if (terMerchantReport.getDeptId().equals(889323L)) {
            return;
        }
        //信创不回退
        if (terMerchantReport.getDeptId().equals(889324L)) {
            return;
        }
        Date today = DateUtils.stringToDate(DateUtils.format(new Date()), DateUtils.DATE_PATTERN);
        String startDateStr = DateUtils.format(terMerchantReport.getCreateDate(), "yyyy-MM-dd");
        //报备时间
        Date startDate = DateUtils.stringToDate(startDateStr, DateUtils.DATE_PATTERN);
        //交易限定结束时间 小于，不包括
        Date endDate = DateUtils.addDateDays(startDate, 5);
        //到达限定结束时间,检查是否有交易
        if (today.compareTo(endDate) == 0) {
            List<TranTransactionInfo> tempList = transactionInfoService.queryListBySnAndTime(terMerchantReport.getSn(), endDate);
            //没有交易，删除报备信息，回退机器
            if (tempList == null || tempList.size() <= 0) {
                //将机器回退至上一层;
                distribuService.rebackTerminalToUpper(terMerchantReport.getSn(), terMerchantReport.getAgentId());
                //删除报备信息
                deleteById(terMerchantReport.getReportId());

                terminalInfoService.unReportTerminal(terMerchantReport.getSn());

                agentService.pushDelMerNotice(terMerchantReport);

            }
        }
    }

    @Override
    public List<Map<String, Object>> queryActivAgent() {
        return baseMapper.queryActivAgent();
    }

    @Override
    public List<TerMerchantReport> queryMerchantByAgentId(Long agentId) {
        return baseMapper.selectList(new EntityWrapper<TerMerchantReport>().eq("agent_id",agentId));
    }

}
